#include "stdafx.h"
#include "Extender.h"
#include "SciTE.h"
#include "GUI.h"
#include <tchar.h>
namespace
{
#define EXT_ID_SETTING	1999
#define EXT_ID_RUN_0	(IDM_TOOLS+1)
#define EXT_ID_RUN_1	(IDM_TOOLS+2)
#define EXT_ID_RUN_2	(IDM_TOOLS+3)
#define EXT_ID_RUN_3	(IDM_TOOLS+4)
#define EXT_ID_RUN_4	(IDM_TOOLS+5)
#define EXT_ID_RUN_5	(IDM_TOOLS+6)
#define EXT_ID_RUN_6	(IDM_TOOLS+7)
#define EXT_ID_RUN_7	(IDM_TOOLS+8)
#define EXT_ID_RUN_8	(IDM_TOOLS+9)
#define EXT_ID_RUN_9	(IDM_TOOLS+10)

#define EXT_POP_MENU	2020
#define MAX_COMMAND_COUNT 3
#define MAX_GROUP_COUNT 60


	struct RUN_COMMAND_PACK 
	{
		std::wstring name;
		std::wstring runCmd;
		int subSystem;
	};

	struct GROUP_COMMAND_PACK
	{
		std::wstring groupName;
		std::vector<RUN_COMMAND_PACK> cmd;
	};

	class RunCmdExtension :public Extension
	{

	public:
		RunCmdExtension()
			:m_pAPI( 0 )
		{
		}
	private:
		bool Initialise(ExtensionAPI *host_)
		{
			m_pAPI = host_;
			return false;
		}
		bool Finalise()
		{
			return false;
		}
		bool Clear()
		{
			return false;
		}
		bool Load(const char *)
		{
			return false;
		}
		virtual bool OnOpen(const char *) 
		{
			processToolBarMenu();
			return false; 
		}
		virtual bool ActivateBuffer(int )
		{
			processToolBarMenu();
			return false; 
		}
		virtual bool OnCommand(int);

		void updateGroupCMD();

		bool isCppFile();
		bool isPascalFile();
		void processToolBarMenu();
		void addToolBarMenu();
		void getAllGroupCmd();
		void popGroupListMenu();
		void getGroupCmd();
		GROUP_COMMAND_PACK getGroupCmd(int nGroupIndex ) const;
		GUI::gui_string getPropertyW( const char* )const;
		std::string getProperty( const char* )const;
	private:
		std::vector<GROUP_COMMAND_PACK> allGroupCmd;
		int defaultGroupIndex;
		ExtensionAPI* m_pAPI;
	};



	void RunCmdExtension::processToolBarMenu()
	{
		if( isCppFile() || isPascalFile() )
		{
			getGroupCmd();
			getAllGroupCmd();
			addToolBarMenu();
			updateGroupCMD();
		}
	}

	bool RunCmdExtension::isCppFile()
	{
		GUI::gui_string strLanguage = getPropertyW( "Language" );

		if( ( GUI_TEXT("cpp") == strLanguage ) || ( GUI_TEXT("c") == strLanguage ) )
		{
			return true;
		}
		return false;
	}


	bool RunCmdExtension::isPascalFile()
	{
		GUI::gui_string strLanguage = getPropertyW( "Language" );

		if( GUI_TEXT("pascal") == strLanguage  )
		{
			return true;
		}
		return false;
	}

	TBBUTTON tbb[] = 
	{
		{ 10 , 0 , TBSTATE_ENABLED , BTNS_SEP , {} , 0 , 0 } ,
		{ STD_PROPERTIES , EXT_ID_SETTING , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
		{ 10 , 0 , TBSTATE_ENABLED , BTNS_SEP , {} , 0 , 0 } ,
		{ STD_PROPERTIES , EXT_ID_RUN_0 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
		{ STD_PROPERTIES , EXT_ID_RUN_1 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
		{ STD_PROPERTIES , EXT_ID_RUN_2 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
//		{ STD_PROPERTIES , EXT_ID_RUN_3 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
// 		{ STD_PROPERTIES , EXT_ID_RUN_4 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
// 		{ STD_PROPERTIES , EXT_ID_RUN_5 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
// 		{ STD_PROPERTIES , EXT_ID_RUN_6 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
// 		{ STD_PROPERTIES , EXT_ID_RUN_7 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
// 		{ STD_PROPERTIES , EXT_ID_RUN_8 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
// 		{ STD_PROPERTIES , EXT_ID_RUN_9 , TBSTATE_ENABLED , BTNS_BUTTON  , {} , 0 , 5 } ,
	};

	void RunCmdExtension::addToolBarMenu( )
	{
		HWND hwndToolBar = (HWND)m_pAPI->getPane( 0 );
		TBBUTTON bt={};
		LRESULT result = ::SendMessage(hwndToolBar , TB_GETBUTTON , 19 ,  reinterpret_cast<LPARAM>(&bt) );
		if( result )
		{
		}
		else
		{
			::SendMessage(hwndToolBar, TB_ADDBUTTONS, _countof(tbb), reinterpret_cast<LPARAM>(tbb));
		}
	}

	std::string RunCmdExtension::getProperty( const char* name )const
	{
		std::auto_ptr<char> pTemp( m_pAPI->Property( name ) );
		return pTemp.get();
	}
	
	GUI::gui_string RunCmdExtension::getPropertyW( const char* name )const
	{
		std::auto_ptr<char> pTemp( m_pAPI->Property( name ) );
		GUI::gui_string str = GUI::StringFromUTF8( pTemp.get() );
		return str;
	}

	void RunCmdExtension::getGroupCmd()
	{
		char szTemp[128]={};
		_snprintf( szTemp , 127 , "cmdex.%s.default.group" , getProperty("Language" ).c_str() );

		GUI::gui_string str = getPropertyW( szTemp ) ;
		if ( str.empty() )
		{
			defaultGroupIndex = 1;
		}
		else
		{
			defaultGroupIndex = _wtoi( str.c_str() );

		}
		if ( 0 == defaultGroupIndex )
		{
			defaultGroupIndex = 1;
		}
	}

	void RunCmdExtension::getAllGroupCmd()
	{
		if( !allGroupCmd.empty() )
		{
			allGroupCmd.clear();
		}

		try
		{
			for ( int i = 1 ; i < MAX_GROUP_COUNT ; ++ i )
			{
				allGroupCmd.push_back( getGroupCmd( i ) );
			}
		}
		catch ( ... )
		{
		}
	}


	GROUP_COMMAND_PACK RunCmdExtension::getGroupCmd( int nGroupIndex )const
	{
		std::string strLanguage = getProperty("Language");
		GROUP_COMMAND_PACK group;
		char szTemp[128]={};
		_snprintf( szTemp , 127 , "cmdex.%s.group.%d.group" , strLanguage.c_str() , nGroupIndex );
		group.groupName = getPropertyW( szTemp );

		if ( group.groupName.empty() )
		{
			throw "group name empty";
		}
		
		for ( int i = 1 ; i < MAX_COMMAND_COUNT ; ++i )
		{
			RUN_COMMAND_PACK cmd;

			_snprintf( szTemp , 127 , "cmdex.%s.group.%d.name.%d" , strLanguage.c_str() , nGroupIndex , i );
			cmd.name = getPropertyW( szTemp ) ;

			_snprintf( szTemp , 127, "cmdex.%s.group.%d.cmd.%d" , strLanguage.c_str() , nGroupIndex , i );	
			cmd.runCmd = getPropertyW( szTemp ) ;

			if ( cmd.name.empty() && cmd.runCmd.empty() )
			{
				break;
			}
			
			_snprintf( szTemp , 127 , "cmdex.%s.group.subsystem.%d" , strLanguage.c_str() , nGroupIndex , i );	
			std::wstring strSubSystem = getPropertyW( szTemp ) ;
			cmd.subSystem = _wtoi( strSubSystem.c_str() );
			
			group.cmd.push_back( cmd );
		}

		return group;
	}
	bool RunCmdExtension::OnCommand( int nCmd)
	{
		switch( nCmd )
		{
		case EXT_ID_SETTING:
			popGroupListMenu();
			break;
		}
		if ( ( nCmd >= EXT_POP_MENU ) 
			&& ( nCmd <= EXT_POP_MENU + MAX_GROUP_COUNT ) )
		{
			defaultGroupIndex = nCmd - EXT_POP_MENU + 1;

			updateGroupCMD();
		}
		return false;
	}

	void RunCmdExtension::popGroupListMenu()
	{
		HWND hMain = (HWND)( m_pAPI->getPane(-1) );
		HMENU hPopMenu = CreatePopupMenu();
		for ( size_t i = 0 ; i < allGroupCmd.size() ; ++i )
		{
			UINT uFlags = MF_STRING;
			if ( i == (size_t)(defaultGroupIndex - 1) )
			{
				uFlags = uFlags | MF_CHECKED;	
			}
			AppendMenu( hPopMenu , uFlags , EXT_POP_MENU + i , allGroupCmd[i].groupName.c_str() );
		}
		POINT pt={};
		GetCursorPos( &pt );
		TrackPopupMenu( hPopMenu , TPM_LEFTBUTTON , pt.x , pt.y , 0 , hMain , NULL );
	}

	void RunCmdExtension::updateGroupCMD()
	{
		std::string strLanguage = getProperty("Language");
		char szName[128]={};
		_snprintf( szName , 127 , "cmdex.%s.default.group" , strLanguage.c_str() );

		char szTemp[128]={};
		_snprintf( szTemp , 31 , "%d" , defaultGroupIndex );
		m_pAPI->SetProperty( szName , szTemp );

		std::string strCmd = GUI::UTF8FromString( allGroupCmd[defaultGroupIndex-1].cmd[0].runCmd );
		if( strLanguage == "cpp" )
		{
			strcpy( szName , "command.1.$(file.patterns.cplusplus)");
		}
		else if(strLanguage == "pascal")
		{
			strcpy( szName , "command.1.$(file.patterns.pascal)");
		}
		m_pAPI->SetProperty( szName , strCmd.c_str() );
	}

}

Extension& RegisterRunCmdExtension()
{
	static RunCmdExtension obj;
	return obj;
}


























